package cn.fintecher.pangolin.service.business.service;

import cn.fintecher.pangolin.common.enums.*;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.Constants;
import cn.fintecher.pangolin.common.utils.DoubleUtil;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.BaseCase;
import cn.fintecher.pangolin.entity.elastic.CaseTransferLog;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.entity.mysql.Department;
import cn.fintecher.pangolin.entity.mysql.QCaseInfo;
import cn.fintecher.pangolin.entity.mysql.User;
import cn.fintecher.pangolin.service.business.model.DistributeConfigModel;
import cn.fintecher.pangolin.service.business.model.DistributeResultModel;
import cn.fintecher.pangolin.service.business.model.request.DistributeAgrsRequest;
import cn.fintecher.pangolin.service.business.model.response.CaseCountAndTotalResponse;
import cn.fintecher.pangolin.service.business.model.response.CaseDistributePreResponse;
import cn.fintecher.pangolin.service.business.model.response.DistributeStatisticalResponse;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.BaseCaseRespository;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.CaseTransferLogRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.CaseInfoRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.DepartmentRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.UserRepository;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.sum.InternalSum;
import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.valuecount.InternalValueCount;
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCountAggregationBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @Author wangxiangdong
 * @Description 案件分配service
 * @Date 2019/9/3 17:55
 **/
@Service
@Slf4j
public class DistributeCaseService {


    @Autowired
    private BaseCaseRespository baseCaseRespository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    @Autowired
    private CaseTransferLogRepository caseTransferLogRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BaseService baseService;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     * @Author wangxiangdong
     * @Description 待分配预览
     * @Date 2019/9/3 18:04
     **/
    public CaseDistributePreResponse caseDistributePreview(DistributeAgrsRequest request) {
        CaseDistributePreResponse response = new CaseDistributePreResponse();
        response.setCaseType(request.getCaseType());
        response.setCaseAmtTotal(request.getCaseAmtTotal());
        response.setDistributeType(request.getDistributeType());
        response.setCaseNumTotal(request.getCaseNumTotal());
        response.setDistributeTotal(request.getDistributeTotal());
        response.setDistributeWay(request.getDistributeWay());
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (!request.getCaseIds().isEmpty()) {
            queryBuilder.must(termsQuery("id.keyword", request.getCaseIds()));
        }
        if (!StringUtils.isBlank(request.getBatchNumber())) {
            queryBuilder.must(matchPhraseQuery("isDistribute.keyword", BaseSelect.NO.name()));
            queryBuilder.must(matchPhraseQuery("batchNumber.keyword", request.getBatchNumber()));
        }
        Iterable<BaseCase> baseCaseIterable = baseCaseRespository.search(queryBuilder);
        LinkedList<BaseCase> personalLinkedList = Lists.newLinkedList(baseCaseIterable);
        /**记录已经满足分配条件的案件分配人员**/
        List<DistributeConfigModel> delDisModelReq = new ArrayList<>();
        if (request.getDistributeWay().equals(DistributeWay.MANUAL_WAY)) {
            //手工分案
            List<DistributeConfigModel> distributeConfigModelsReq = request.getDistributeConfigModels();
            List<DistributeResultModel> distributeResults = new ArrayList<>();
            proManualDistribute(distributeConfigModelsReq, personalLinkedList, request.getCaseNumTotal(), request.getCaseAmtTotal(), distributeResults, delDisModelReq);
            response.setDistributeConfigModels(distributeResults);
        } else {
            //将案件按金额从大到小排序
            personalLinkedList.sort(Comparator.comparing((BaseCase baseCase) -> baseCase.getLeftAmt()));
            //平均金额
            double leftAmtAvg = new BigDecimal(request.getCaseAmtTotal()).
                    divide(new BigDecimal(request.getDistributeConfigModels().size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
            //平均案件数
            long caseTotalsAvg = request.getCaseNumTotal() / request.getDistributeTotal();
            if (caseTotalsAvg == 0) {
                caseTotalsAvg = 1;
            }
            List<DistributeConfigModel> distributeConfigModelsReq = request.getDistributeConfigModels();
            List<DistributeResultModel> distributeResults = new ArrayList<>();
            proSysDistribute(distributeConfigModelsReq, personalLinkedList, leftAmtAvg, caseTotalsAvg, request.getCaseNumTotal(),
                    request.getCaseAmtTotal(), distributeResults, delDisModelReq);
            response.setDistributeConfigModels(distributeResults);
        }
        return response;
    }

    /**
     * @Author wangxiangdong
     * @Description 机构待分配预览
     * @Date 2019/9/3 18:04
     **/
    public CaseDistributePreResponse orgCaseDistributePreview(DistributeAgrsRequest request) {
        CaseDistributePreResponse response = new CaseDistributePreResponse();
        response.setCaseAmtTotal(request.getCaseAmtTotal());
        response.setDistributeType(request.getDistributeType());
        response.setCaseNumTotal(request.getCaseNumTotal());
        response.setDistributeTotal(request.getDistributeTotal());
        response.setDistributeWay(request.getDistributeWay());
        response.setDistributePoolType(request.getDistributePoolType());
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (!request.getCaseIds().isEmpty()) {
            booleanBuilder.and(QCaseInfo.caseInfo.id.in(request.getCaseIds()));
        }
        if (!StringUtils.isBlank(request.getBatchNumber()) && Objects.equals(request.getDistributePoolType(), DistributePoolType.ORG_POOL)) {
            booleanBuilder.and(QCaseInfo.caseInfo.batchNumber.eq(request.getBatchNumber()));
            booleanBuilder.and(QCaseInfo.caseInfo.department.isNotNull());
        }
        if (!StringUtils.isBlank(request.getBatchNumber()) && Objects.equals(request.getDistributePoolType(), DistributePoolType.IN_POOL)) {
            booleanBuilder.and(QCaseInfo.caseInfo.batchNumber.eq(request.getBatchNumber()));
            booleanBuilder.and(QCaseInfo.caseInfo.caseDataStatus.eq(CaseDataStatus.IN_POOL));
        }
        if (!StringUtils.isBlank(request.getBatchNumber()) && Objects.equals(request.getDistributePoolType(), DistributePoolType.CIRCULATION)) {
            booleanBuilder.and(QCaseInfo.caseInfo.batchNumber.eq(request.getBatchNumber()));
            booleanBuilder.and(QCaseInfo.caseInfo.caseDataStatus.eq(CaseDataStatus.CIRCULATION));
        }
        Iterable<CaseInfo> caseInfoRepositoryAll = caseInfoRepository.findAll(booleanBuilder);
        LinkedList<CaseInfo> caseInfoLinkedList = Lists.newLinkedList(caseInfoRepositoryAll);
        /**记录已经满足分配条件的案件分配人员**/
        List<DistributeConfigModel> delDisModelReq = new ArrayList<>();
        if (request.getDistributeWay().equals(DistributeWay.MANUAL_WAY)) {
            //手工分案
            List<DistributeConfigModel> distributeConfigModelsReq = request.getDistributeConfigModels();
            List<DistributeResultModel> distributeResults = new ArrayList<>();
            orgManualDistribute(distributeConfigModelsReq, caseInfoLinkedList, request.getCaseNumTotal(), request.getCaseAmtTotal(),
                    distributeResults, delDisModelReq);
            response.setDistributeConfigModels(distributeResults);
        } else {
            //将案件按金额从大到小排序
            caseInfoLinkedList.sort(Comparator.comparing(CaseInfo::getLeftAmt));
            //平均金额
            double leftAmtAvg = new BigDecimal(request.getCaseAmtTotal()).
                    divide(new BigDecimal(request.getDistributeConfigModels().size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
            //平均案件数
            long caseTotalsAvg = request.getCaseNumTotal() / request.getDistributeTotal();
            if (caseTotalsAvg == 0) {
                caseTotalsAvg = 1;
            }
            List<DistributeConfigModel> distributeConfigModelsReq = request.getDistributeConfigModels();
            List<DistributeResultModel> distributeResults = new ArrayList<>();
            orgSysDistributePre(distributeConfigModelsReq, caseInfoLinkedList, leftAmtAvg, caseTotalsAvg, request.getCaseNumTotal(),
                    request.getCaseAmtTotal(), distributeResults, delDisModelReq);
            response.setDistributeConfigModels(distributeResults);
        }
        return response;
    }

    public void orgSysDistributePre(List<DistributeConfigModel> distributeConfigModelList, LinkedList<CaseInfo> caseInfoLinkedList,
                                    double leftAmtAvg, long caseTotalsAvg, long caseNumTotal, double caseAmtTotal,
                                    List<DistributeResultModel> distributeResults, List<DistributeConfigModel> delDisModelReq) {
        //案件接收为一时,案件直接分配
        if (distributeConfigModelList.size() == 1) {
            //催收员分配数据
            DistributeConfigModel req = distributeConfigModelList.get(0);
            DistributeResultModel resultModel = null;
            if (!distributeResults.isEmpty()) {
                resultModel = distributeResults.get(0);
            } else {
                resultModel = new DistributeResultModel();
                BeanUtils.copyProperties(req, resultModel);
                distributeResults.add(resultModel);
            }
            resultModel.setPerNum(1.0);
            resultModel.setLimitAmt(leftAmtAvg);
            resultModel.setLimitNum(caseTotalsAvg);
            //分配案件数
            resultModel.setCaseNumTotal(caseNumTotal);
            //分配金额数
            resultModel.setLeftAmtTotal(caseAmtTotal);
            for (CaseInfo obj : caseInfoLinkedList) {
                resultModel.getResultMap().put(obj.getId(), obj.getLeftAmt());
            }
        } else {
            /**剔除已经满足分配条件的催收员**/
            if (Objects.nonNull(delDisModelReq) && !delDisModelReq.isEmpty()) {
                distributeConfigModelList.removeAll(delDisModelReq);
            }
            /**根据工号分组分配结果**/
            Map<String, DistributeResultModel> resMap = distributeResults.stream().collect(Collectors.toMap(DistributeResultModel::getId, e -> e));
            for (DistributeConfigModel req : distributeConfigModelList) {
                Boolean addFlag = true;
                DistributeResultModel resModel = null;
                if (resMap.containsKey(req.getId())) {
                    resModel = resMap.get(req.getId());
                    addFlag = false;
                } else {
                    resModel = new DistributeResultModel();
                    BeanUtils.copyProperties(req, resModel);
                    resModel.setLimitAmt(leftAmtAvg);
                    resModel.setLimitNum(caseTotalsAvg);
                }
                while (true) {
                    if (caseInfoLinkedList.isEmpty()) {
                        double perNum = DoubleUtil.div(resModel.getCaseNumTotal(), caseNumTotal, 4);
                        resModel.setPerNum(perNum);
                        if (addFlag) {
                            distributeResults.add(resModel);
                        }
                        break;
                    }
                    //取低位值
                    CaseInfo low = caseInfoLinkedList.getFirst();
                    //分配案件数
                    resModel.setCaseNumTotal(resModel.getCaseNumTotal() + 1);
                    //分配金额数
                    resModel.setLeftAmtTotal(DoubleUtil.sum(low.getLeftAmt(), resModel.getLeftAmtTotal(), 2));
                    resModel.getResultMap().put(low.getId(), low.getLeftAmt());
                    caseInfoLinkedList.remove(low);
                    //判断是否满足限制条件
                    if (resModel.getLeftAmtTotal() >= leftAmtAvg || resModel.getCaseNumTotal() >= caseTotalsAvg) {
                        double perNum = DoubleUtil.div(resModel.getCaseNumTotal(), caseNumTotal, 4);
                        resModel.setPerNum(perNum);
                        if (addFlag) {
                            distributeResults.add(resModel);
                        }
                        //取下一个催员
                        break;
                    } else {
                        //取高位
                        if (!caseInfoLinkedList.isEmpty()) {
                            CaseInfo high = caseInfoLinkedList.getLast();
                            //分配数量
                            resModel.setCaseNumTotal(resModel.getCaseNumTotal() + 1);
                            //分配金额
                            resModel.setLeftAmtTotal(DoubleUtil.sum(high.getLeftAmt(), resModel.getLeftAmtTotal(), 2));
                            resModel.getResultMap().put(high.getId(), high.getLeftAmt());
                            caseInfoLinkedList.remove(high);
                            //判断是否满足限制条件
                            if (resModel.getLeftAmtTotal() >= leftAmtAvg || resModel.getCaseNumTotal() >= caseTotalsAvg) {
                                double perNum = DoubleUtil.div(resModel.getCaseNumTotal(), caseNumTotal, 4);
                                resModel.setPerNum(perNum);
                                if (addFlag) {
                                    distributeResults.add(resModel);
                                }
                                break;
                            }
                        }
                    }
                }
            }
            //处理剩余未分配的案子
            if (!caseInfoLinkedList.isEmpty()) {
                distributeOrgLeafList(caseInfoLinkedList, distributeResults, caseNumTotal);
            }
        }
    }

    private void orgManualDistribute(List<DistributeConfigModel> distributeConfigModelList, LinkedList<CaseInfo> caseInfoLinkedList,
                                     long caseNumTotal, double caseAmtTotal, List<DistributeResultModel> distributeResults,
                                     List<DistributeConfigModel> delDisModelReq) {
        //如果分配单位为1,直接分配
        if (distributeConfigModelList.size() == 1) {
            DistributeConfigModel req = distributeConfigModelList.get(0);
            DistributeResultModel resultModel = null;
            if (!distributeResults.isEmpty()) {
                resultModel = distributeResults.get(0);
            } else {
                resultModel = new DistributeResultModel();
                BeanUtils.copyProperties(req, resultModel);
                distributeResults.add(resultModel);
            }
            resultModel.setPerNum(1.0);
            //分配案件数
            resultModel.setCaseNumTotal(caseNumTotal);
            //分配金额数
            resultModel.setLeftAmtTotal(caseAmtTotal);
            for (CaseInfo caseInfo : caseInfoLinkedList) {
                resultModel.getResultMap().put(caseInfo.getId(), caseInfo.getLeftAmt());
            }
        } else {
            /**剔除已经满足分配条件的催收员**/
            if (!delDisModelReq.isEmpty()) {
                distributeConfigModelList.removeAll(delDisModelReq);
            }
            /**根据Id分组分配结果**/
            Map<String, DistributeResultModel> resMap = distributeResults.stream().collect(Collectors.toMap(DistributeResultModel::getId, e -> e));
            for (DistributeConfigModel req : distributeConfigModelList) {
                Boolean addFlag = true;
                DistributeResultModel resultModel = null;
                if (resMap.containsKey(req.getId())) {
                    resultModel = resMap.get(req.getId());
                    addFlag = false;
                } else {
                    resultModel = new DistributeResultModel();
                    BeanUtils.copyProperties(req, resultModel);
                }
                while (true) {
                    if (caseInfoLinkedList.isEmpty()) {
                        //分配案件数量百分比
                        double perNum = DoubleUtil.div(resultModel.getCaseNumTotal(), caseNumTotal, 4);
                        resultModel.setPerNum(perNum);
                        delDisModelReq.add(req);
                        if (addFlag) {
                            distributeResults.add(resultModel);
                        }
                        break;
                    }
                    //取低位值
                    CaseInfo low = caseInfoLinkedList.getFirst();
                    //分配案件数
                    resultModel.setCaseNumTotal(resultModel.getCaseNumTotal() + 1);
                    //分配金额数
                    resultModel.setLeftAmtTotal(DoubleUtil.sum(low.getLeftAmt(), resultModel.getLeftAmtTotal(), 2));
                    resultModel.getResultMap().put(low.getId(), low.getLeftAmt());
                    caseInfoLinkedList.remove(low);
                    //判断是否满足限制条件
                    if (resultModel.getLeftAmtTotal() >= resultModel.getLimitAmt() || resultModel.getCaseNumTotal() >= resultModel.getLimitNum()) {
                        double perNum = DoubleUtil.div(resultModel.getCaseNumTotal(), caseNumTotal, 4);
                        resultModel.setPerNum(perNum);
                        delDisModelReq.add(req);
                        if (addFlag) {
                            distributeResults.add(resultModel);
                        }
                        //取下一个催员
                        break;
                    } else {
                        //取高位
                        if (!caseInfoLinkedList.isEmpty()) {
                            CaseInfo high = caseInfoLinkedList.getLast();
                            //分配数量
                            resultModel.setCaseNumTotal(resultModel.getCaseNumTotal() + 1);
                            //分配金额
                            resultModel.setLeftAmtTotal(DoubleUtil.sum(high.getLeftAmt(), resultModel.getLeftAmtTotal(), 2));
                            resultModel.getResultMap().put(high.getId(), high.getLeftAmt());
                            caseInfoLinkedList.remove(high);
                            //判断是否满足限制条件
                            if (resultModel.getLeftAmtTotal() >= resultModel.getLimitAmt() ||
                                    resultModel.getCaseNumTotal() >= resultModel.getLimitNum()) {
                                double perNum = DoubleUtil.div(resultModel.getCaseNumTotal(), caseNumTotal, 4);
                                resultModel.setPerNum(perNum);
                                delDisModelReq.add(req);
                                if (addFlag) {
                                    distributeResults.add(resultModel);
                                }
                                //取下一个催员
                                break;
                            }
                        }
                    }
                }
            }
            //处理剩余未分配的案子
            if (!caseInfoLinkedList.isEmpty()) {
                distributeOrgLeafList(caseInfoLinkedList, distributeResults, caseNumTotal);
            }
        }
    }

    /**
     * 执行案件分配(手动分案)
     *
     * @param distributeConfigModelList 催收员数据
     * @param baseCaseLinkedList        剩余案件数据
     * @param caseNumTotal              案件总数量
     * @param caseAmtTotal              案件总金额
     * @param distributeResults         共债分配结果
     * @param delDisModelReq            已经满足分配结果的催收员
     */
    public void proManualDistribute(List<DistributeConfigModel> distributeConfigModelList, LinkedList<BaseCase> baseCaseLinkedList,
                                    long caseNumTotal, double caseAmtTotal, List<DistributeResultModel> distributeResults,
                                    List<DistributeConfigModel> delDisModelReq) {
        //如果分配单位为1,直接分配
        if (distributeConfigModelList.size() == 1) {
            DistributeConfigModel req = distributeConfigModelList.get(0);
            DistributeResultModel resultModel = null;
            if (!distributeResults.isEmpty()) {
                resultModel = distributeResults.get(0);
            } else {
                resultModel = new DistributeResultModel();
                BeanUtils.copyProperties(req, resultModel);
                distributeResults.add(resultModel);
            }
            resultModel.setPerNum(1.0);
            //分配案件数
            resultModel.setCaseNumTotal(caseNumTotal);
            //分配金额数
            resultModel.setLeftAmtTotal(caseAmtTotal);
            for (BaseCase baseCase : baseCaseLinkedList) {
                resultModel.getResultMap().put(baseCase.getId(), baseCase.getLeftAmt());
            }
        } else {
            /**剔除已经满足分配条件的催收员**/
            if (!delDisModelReq.isEmpty()) {
                distributeConfigModelList.removeAll(delDisModelReq);
            }
            /**根据Id分组分配结果**/
            Map<String, DistributeResultModel> resMap = distributeResults.stream().collect(Collectors.toMap(DistributeResultModel::getId, e -> e));
            for (DistributeConfigModel req : distributeConfigModelList) {
                Boolean addFlag = true;
                DistributeResultModel resultModel = null;
                if (resMap.containsKey(req.getId())) {
                    resultModel = resMap.get(req.getId());
                    addFlag = false;
                } else {
                    resultModel = new DistributeResultModel();
                    BeanUtils.copyProperties(req, resultModel);
                }
                while (true) {
                    if (baseCaseLinkedList.isEmpty()) {
                        //分配案件数量百分比
                        double perNum = DoubleUtil.div(resultModel.getCaseNumTotal(), caseNumTotal, 4);
                        resultModel.setPerNum(perNum);
                        delDisModelReq.add(req);
                        if (addFlag) {
                            distributeResults.add(resultModel);
                        }
                        break;
                    }
                    //取低位值
                    BaseCase low = baseCaseLinkedList.getFirst();
                    //分配案件数
                    resultModel.setCaseNumTotal(resultModel.getCaseNumTotal() + 1);
                    //分配金额数
                    resultModel.setLeftAmtTotal(DoubleUtil.sum(low.getLeftAmt(), resultModel.getLeftAmtTotal(), 2));
                    resultModel.getResultMap().put(low.getId(), low.getLeftAmt());
                    baseCaseLinkedList.remove(low);
                    //判断是否满足限制条件
                    if (resultModel.getLeftAmtTotal() >= resultModel.getLimitAmt() || resultModel.getCaseNumTotal() >= resultModel.getLimitNum()) {
                        double perNum = DoubleUtil.div(resultModel.getCaseNumTotal(), caseNumTotal, 4);
                        resultModel.setPerNum(perNum);
                        delDisModelReq.add(req);
                        if (addFlag) {
                            distributeResults.add(resultModel);
                        }
                        //取下一个分配对象
                        break;
                    } else {
                        //取高位
                        if (!baseCaseLinkedList.isEmpty()) {
                            BaseCase high = baseCaseLinkedList.getLast();
                            //分配数量
                            resultModel.setCaseNumTotal(resultModel.getCaseNumTotal() + 1);
                            //分配金额
                            resultModel.setLeftAmtTotal(DoubleUtil.sum(high.getLeftAmt(), resultModel.getLeftAmtTotal(), 2));
                            resultModel.getResultMap().put(high.getId(), high.getLeftAmt());
                            baseCaseLinkedList.remove(high);
                            //判断是否满足限制条件
                            if (resultModel.getLeftAmtTotal() >= resultModel.getLimitAmt() ||
                                    resultModel.getCaseNumTotal() >= resultModel.getLimitNum()) {
                                double perNum = DoubleUtil.div(resultModel.getCaseNumTotal(), caseNumTotal, 4);
                                resultModel.setPerNum(perNum);
                                delDisModelReq.add(req);
                                if (addFlag) {
                                    distributeResults.add(resultModel);
                                }
                                //取下一个分配对象
                                break;
                            }
                        }
                    }
                }
            }
            //处理剩余未分配的案子
            if (!baseCaseLinkedList.isEmpty()) {
                distributeLeafList(baseCaseLinkedList, distributeResults, caseNumTotal);
            }
        }
    }

    /**
     * @Author wangxiangdong
     * @Description 机构待分配分配剩余未分配出去的案子(数量分配)
     * @Date 2019/9/7 14:22
     **/
    private void distributeOrgLeafList(LinkedList<CaseInfo> leftBaseList, List<DistributeResultModel> distributeResults, long caseNumTotal) {
        //将分配结果从小到大排序
        distributeResults.sort(Comparator.comparing(DistributeResultModel::getCaseNumTotal));
        //剩余案子大于分配人员时
        if (leftBaseList.size() > distributeResults.size()) {
            //计算剩余案件每个催员的平均值
            //平均数
            int pageSize = leftBaseList.size() / distributeResults.size();
            //总页数
            int copyCount = 0;
            if (leftBaseList.size() % pageSize > 0) {
                copyCount = leftBaseList.size() / pageSize + 1;
            } else {
                copyCount = leftBaseList.size() / pageSize;
            }
            for (int pageNo = 1; pageNo <= copyCount; pageNo++) {
                int startIndex = pageSize * (pageNo - 1);
                int endIndex = pageSize * pageNo;
                if (endIndex > leftBaseList.size()) {
                    endIndex = leftBaseList.size();
                }
                List<CaseInfo> pageCaseList = leftBaseList.subList(startIndex, endIndex);
                if (pageNo <= distributeResults.size()) {
                    DistributeResultModel res = distributeResults.get(pageNo - 1);
                    for (CaseInfo caseInfo : pageCaseList) {
                        res.setCaseNumTotal(res.getCaseNumTotal() + 1);
                        res.setLeftAmtTotal(DoubleUtil.sum(res.getLeftAmtTotal(), caseInfo.getLeftAmt(), 2));
                        res.getResultMap().put(caseInfo.getId(), caseInfo.getLeftAmt());
                        double perNum = DoubleUtil.div(res.getCaseNumTotal(), caseNumTotal, 4);
                        res.setPerNum(perNum);
                    }
                } else {
                    //最后一页
                    //将分配结果从小到大排序
                    distributeResults.sort(Comparator.comparing(DistributeResultModel::getCaseNumTotal));
                    for (int k = 0; k < distributeResults.size(); k++) {
                        DistributeResultModel res = distributeResults.get(k);
                        if (k < pageCaseList.size()) {
                            res.setCaseNumTotal(res.getCaseNumTotal() + 1);
                            res.setLeftAmtTotal(DoubleUtil.sum(res.getLeftAmtTotal(), pageCaseList.get(k).getLeftAmt(), 2));
                            res.getResultMap().put(pageCaseList.get(k).getId(), pageCaseList.get(k).getLeftAmt());
                            double perNum = DoubleUtil.div(res.getCaseNumTotal(), caseNumTotal, 4);
                            res.setPerNum(perNum);
                        } else {
                            break;
                        }
                    }
                }
            }
        } else {
            for (int k = 0; k < distributeResults.size(); k++) {
                DistributeResultModel res = distributeResults.get(k);
                if (k < leftBaseList.size()) {
                    res.setCaseNumTotal(res.getCaseNumTotal() + 1);
                    res.setLeftAmtTotal(DoubleUtil.sum(res.getLeftAmtTotal(), leftBaseList.get(k).getLeftAmt(), 2));
                    res.getResultMap().put(leftBaseList.get(k).getId(), leftBaseList.get(k).getLeftAmt());
                    double perNum = DoubleUtil.div(res.getCaseNumTotal(), caseNumTotal, 4);
                    res.setPerNum(perNum);
                } else {
                    break;
                }
            }
        }
    }


    /**
     * 处理机构待分配剩余未分配出去的案子(数量分配)
     *
     * @param leftBaseList
     * @param distributeResults
     */
    private void distributeLeafList(LinkedList<BaseCase> leftBaseList, List<DistributeResultModel> distributeResults, long caseNumTotal) {
        //将分配结果从小到大排序
        distributeResults.sort(Comparator.comparing(DistributeResultModel::getCaseNumTotal));
        //剩余案子大于分配人员时
        if (leftBaseList.size() > distributeResults.size()) {
            //计算剩余案件每个催员的平均值
            //平均数
            int pageSize = leftBaseList.size() / distributeResults.size();
            //总页数
            int copyCount = 0;
            if (leftBaseList.size() % pageSize > 0) {
                copyCount = leftBaseList.size() / pageSize + 1;
            } else {
                copyCount = leftBaseList.size() / pageSize;
            }
            for (int pageNo = 1; pageNo <= copyCount; pageNo++) {
                int startIndex = pageSize * (pageNo - 1);
                int endIndex = pageSize * pageNo;
                if (endIndex > leftBaseList.size()) {
                    endIndex = leftBaseList.size();
                }
                List<BaseCase> baseCaseList = leftBaseList.subList(startIndex, endIndex);
                if (pageNo <= distributeResults.size()) {
                    DistributeResultModel res = distributeResults.get(pageNo - 1);
                    for (BaseCase baseCase : baseCaseList) {
                        res.setCaseNumTotal(res.getCaseNumTotal() + 1);
                        res.setLeftAmtTotal(DoubleUtil.sum(res.getLeftAmtTotal(), baseCase.getLeftAmt(), 2));
                        res.getResultMap().put(baseCase.getId(), baseCase.getLeftAmt());
                        double perNum = DoubleUtil.div(res.getCaseNumTotal(), caseNumTotal, 4);
                        res.setPerNum(perNum);
                    }
                } else {
                    //最后一页
                    //将分配结果从小到大排序
                    distributeResults.sort(Comparator.comparing(DistributeResultModel::getCaseNumTotal));
                    for (int k = 0; k < distributeResults.size(); k++) {
                        DistributeResultModel res = distributeResults.get(k);
                        if (k < baseCaseList.size()) {
                            res.setCaseNumTotal(res.getCaseNumTotal() + 1);
                            res.setLeftAmtTotal(DoubleUtil.sum(res.getLeftAmtTotal(), baseCaseList.get(k).getLeftAmt(), 2));
                            res.getResultMap().put(baseCaseList.get(k).getId(), baseCaseList.get(k).getLeftAmt());
                            double perNum = DoubleUtil.div(res.getCaseNumTotal(), caseNumTotal, 4);
                            res.setPerNum(perNum);
                        } else {
                            break;
                        }
                    }
                }
            }
        } else {
            for (int k = 0; k < distributeResults.size(); k++) {
                DistributeResultModel res = distributeResults.get(k);
                if (k < leftBaseList.size()) {
                    res.setCaseNumTotal(res.getCaseNumTotal() + 1);
                    res.setLeftAmtTotal(DoubleUtil.sum(res.getLeftAmtTotal(), leftBaseList.get(k).getLeftAmt(), 2));
                    res.getResultMap().put(leftBaseList.get(k).getId(), leftBaseList.get(k).getLeftAmt());
                    double perNum = DoubleUtil.div(res.getCaseNumTotal(), caseNumTotal, 4);
                    res.setPerNum(perNum);
                } else {
                    break;
                }
            }
        }
    }


    /**
     * 分案规则如下：
     * 1、案件接收人做第一级循环，将案件金额从大到小顺序排列；
     * 2、计算接收人可接受案件数量及金额平均值，每次取队列中最大值和最小值，给接收人；
     * 3、当取最大值时已经超过数量或金额平均中的任何一个则最小值由新接收人接收案件。依次类推；
     * 4、如果所有接收人都到达最大值限制,则接收人案件数量从下到大排序，将剩余案子再次算平均值，依次增加给案件接收人；
     *
     * @param distributeConfigModelList 接受案件催员
     * @param baseCaseLinkedList        需要分配的案件
     * @param leftAmtAvg                平均金额
     * @param caseTotalsAvg             平均数量
     * @param caseNumTotal              案件总数
     * @param caseAmtTotal              金额总数
     * @param distributeResults         分配结果
     * @param delDisModelReq            已经满足分配条件的催员
     */
    public void proSysDistribute(List<DistributeConfigModel> distributeConfigModelList, LinkedList<BaseCase> baseCaseLinkedList,
                                 double leftAmtAvg, long caseTotalsAvg, long caseNumTotal, double caseAmtTotal,
                                 List<DistributeResultModel> distributeResults, List<DistributeConfigModel> delDisModelReq) {
        //案件接收为一时,案件直接分配
        if (distributeConfigModelList.size() == 1) {
            //催收员分配数据
            DistributeConfigModel req = distributeConfigModelList.get(0);
            DistributeResultModel resultModel = null;
            if (!distributeResults.isEmpty()) {
                resultModel = distributeResults.get(0);
            } else {
                resultModel = new DistributeResultModel();
                BeanUtils.copyProperties(req, resultModel);
                distributeResults.add(resultModel);
            }
            resultModel.setPerNum(1.0);
            resultModel.setLimitAmt(leftAmtAvg);
            resultModel.setLimitNum(caseTotalsAvg);
            //分配案件数
            resultModel.setCaseNumTotal(caseNumTotal);
            //分配金额数
            resultModel.setLeftAmtTotal(caseAmtTotal);
            for (BaseCase obj : baseCaseLinkedList) {
                resultModel.getResultMap().put(obj.getId(), obj.getLeftAmt());
            }
        } else {
            /**剔除已经满足分配条件的催收员**/
            if (Objects.nonNull(delDisModelReq) && !delDisModelReq.isEmpty()) {
                distributeConfigModelList.removeAll(delDisModelReq);
            }
            /**根据工号分组分配结果**/
            Map<String, DistributeResultModel> resMap = distributeResults.stream().collect(Collectors.toMap(DistributeResultModel::getId, e -> e));
            for (DistributeConfigModel req : distributeConfigModelList) {
                Boolean addFlag = true;
                DistributeResultModel resModel = null;
                if (resMap.containsKey(req.getId())) {
                    resModel = resMap.get(req.getId());
                    addFlag = false;
                } else {
                    resModel = new DistributeResultModel();
                    BeanUtils.copyProperties(req, resModel);
                    resModel.setLimitAmt(leftAmtAvg);
                    resModel.setLimitNum(caseTotalsAvg);
                }
                while (true) {
                    if (baseCaseLinkedList.isEmpty()) {
                        double perNum = DoubleUtil.div(resModel.getCaseNumTotal(), caseNumTotal, 4);
                        resModel.setPerNum(perNum);
                        if (addFlag) {
                            distributeResults.add(resModel);
                        }
                        break;
                    }
                    //取低位值
                    BaseCase low = baseCaseLinkedList.getFirst();
                    //分配案件数
                    resModel.setCaseNumTotal(resModel.getCaseNumTotal() + 1);
                    //分配金额数
                    resModel.setLeftAmtTotal(DoubleUtil.sum(low.getLeftAmt(), resModel.getLeftAmtTotal(), 2));
                    resModel.getResultMap().put(low.getId(), low.getLeftAmt());
                    baseCaseLinkedList.remove(low);
                    //判断是否满足限制条件
                    if (resModel.getLeftAmtTotal() >= leftAmtAvg || resModel.getCaseNumTotal() >= caseTotalsAvg) {
                        double perNum = DoubleUtil.div(resModel.getCaseNumTotal(), caseNumTotal, 4);
                        resModel.setPerNum(perNum);
                        if (addFlag) {
                            distributeResults.add(resModel);
                        }
                        //取下一个分配对象
                        break;
                    } else {
                        //取高位
                        if (!baseCaseLinkedList.isEmpty()) {
                            BaseCase high = baseCaseLinkedList.getLast();
                            //分配数量
                            resModel.setCaseNumTotal(resModel.getCaseNumTotal() + 1);
                            //分配金额
                            resModel.setLeftAmtTotal(DoubleUtil.sum(high.getLeftAmt(), resModel.getLeftAmtTotal(), 2));
                            resModel.getResultMap().put(high.getId(), high.getLeftAmt());
                            baseCaseLinkedList.remove(high);
                            //判断是否满足限制条件
                            if (resModel.getLeftAmtTotal() >= leftAmtAvg || resModel.getCaseNumTotal() >= caseTotalsAvg) {
                                double perNum = DoubleUtil.div(resModel.getCaseNumTotal(), caseNumTotal, 4);
                                resModel.setPerNum(perNum);
                                if (addFlag) {
                                    distributeResults.add(resModel);
                                }
                                break;
                            }
                        }
                    }
                }
            }
            //处理剩余未分配的案子
            if (!baseCaseLinkedList.isEmpty()) {
                distributeLeafList(baseCaseLinkedList, distributeResults, caseNumTotal);
            }
        }
    }

    /**
     * @Author wangxiangdong
     * @Description 机构手动分案确认
     * @Date 2019/9/4 9:43
     **/
    @Transactional
    public void confirmDistributeCaseForDepartment(CaseDistributePreResponse request, UserModel userModel) {
        List<CaseInfo> caseInfoList = new ArrayList<>();
        List<CaseTransferLog> caseTransferLogList = new ArrayList<>();
        List<BaseCase> updatePersonal = new ArrayList<>();
        for (DistributeResultModel distributeResultModel : request.getDistributeConfigModels()) {
            String deptId = distributeResultModel.getId();
            Department department = departmentRepository.getOne(deptId);
            Map<String, Double> resultMap = distributeResultModel.getResultMap();
            List<String> caseIds = new ArrayList<>();
            for (Map.Entry<String, Double> entry : resultMap.entrySet()) {
                caseIds.add(entry.getKey());
            }
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(termsQuery("id.keyword", caseIds));
            Iterator<BaseCase> iterator = baseCaseRespository.search(queryBuilder).iterator();
            while (iterator.hasNext()) {
                BaseCase baseCase = iterator.next();
                CaseInfo caseInfo = new CaseInfo();
                BeanUtils.copyProperties(baseCase, caseInfo);
                caseInfo.setTransferDate(ZWDateUtil.getNowDateTime());
                caseInfo.setAddress(baseCase.getHomeAddr());
                caseInfo.setCaseType(request.getCaseType());
                caseInfo.setPublicCaseFlag(PublicCaseFlag.NO_PUBLIC_CASE);
                caseInfo.setDepartment(department);
                caseInfo.setOperator(userModel.getRealName());
                caseInfo.setOperatorTime(ZWDateUtil.getNowDateTime());
                caseInfo.setLastContactResult(null);
                caseInfo.setLastContactDate(null);
                caseTransferLogList.add(baseService.createCaseTranferLog(baseCase.getId(), "手动分案:分案到【".concat(department.getName()).concat("】"), userModel, null, null,caseInfo.getLeftAmt()));
                caseInfoList.add(caseInfo);
                baseCase.setIsDistribute(BaseSelect.YES);
                updatePersonal.add(baseCase);
            }
        }
        caseInfoRepository.saveAll(caseInfoList);
        baseCaseRespository.saveAll(updatePersonal);
        caseTransferLogRepository.saveAll(caseTransferLogList);
    }

    /**
     * @Author wangxiangdong
     * @Description 机构待分配手动分案确认
     * @Date 2019/9/4 9:43
     **/
    @Transactional
    public void orgConfirmCase(List<DistributeResultModel> distributeResultModelList, UserModel userModel) {
        List<CaseInfo> caseInfoList = new ArrayList<>();
        List<CaseTransferLog> caseTransferLogList = new ArrayList<>();
        for (DistributeResultModel distributeResultModel : distributeResultModelList) {
            String deptId = distributeResultModel.getId();
            Department department = departmentRepository.getOne(deptId);
            Map<String, Double> resultMap = distributeResultModel.getResultMap();
            List<String> caseIds = new ArrayList<>();
            for (Map.Entry<String, Double> entry : resultMap.entrySet()) {
                caseIds.add(entry.getKey());
            }
            BooleanBuilder booleanBuilder = new BooleanBuilder();
            booleanBuilder.and(QCaseInfo.caseInfo.id.in(caseIds));
            Iterator<CaseInfo> iterator = caseInfoRepository.findAll(booleanBuilder).iterator();
            while (iterator.hasNext()) {
                CaseInfo caseInfo = iterator.next();
                caseInfo.setTransferDate(ZWDateUtil.getNowDateTime());
                String outUserId = (Objects.isNull(caseInfo.getCurrentCollector()) ? null : caseInfo.getCurrentCollector().getId());
                caseInfo.setDepartment(department);
                caseInfo.setCurrentCollector(null);
                caseInfo.setCaseDataStatus(null);
                caseInfo.setOperator(userModel.getRealName());
                caseInfo.setLastContactResult(null);
                caseInfo.setLastContactDate(null);
                caseInfo.setOperatorTime(ZWDateUtil.getNowDateTime());
                caseInfo.setUpdateDate(ZWDateUtil.getNowDateTime());
                caseInfo.setUpdatePersonName(userModel.getRealName());
                caseTransferLogList.add(baseService.createCaseTranferLog(caseInfo.getId(), "手动分案:分案到【".concat(department.getName()).concat("】"), userModel, outUserId, null,caseInfo.getLeftAmt()));
                caseInfoList.add(caseInfo);
            }
        }
        caseInfoRepository.saveAll(caseInfoList);
        caseTransferLogRepository.saveAll(caseTransferLogList);
    }


    /**
     * @Author wangxiangdong
     * @Description 待分配催收员手动分案确认
     * @Date 2019/9/4 9:43
     **/
    @Transactional
    public void confirmDistributeCaseForCollector(CaseDistributePreResponse request, UserModel userModel) {
        List<CaseInfo> caseInfoList = new ArrayList<>();
        List<CaseTransferLog> caseTransferLogList = new ArrayList<>();
        List<BaseCase> updateBaseCase = new ArrayList<>();
        for (DistributeResultModel distributeResultModel : request.getDistributeConfigModels()) {
            String userId = distributeResultModel.getId();
            User user = userRepository.getOne(userId);
            Map<String, Double> resultMap = distributeResultModel.getResultMap();
            List<String> caseIds = new ArrayList<>();
            for (Map.Entry<String, Double> entry : resultMap.entrySet()) {
                caseIds.add(entry.getKey());
            }
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(termsQuery("id.keyword", caseIds));
            Iterator<BaseCase> iterator = baseCaseRespository.search(queryBuilder).iterator();
            while (iterator.hasNext()) {
                BaseCase baseCase = iterator.next();
                CaseInfo caseInfo = new CaseInfo();
                BeanUtils.copyProperties(baseCase, caseInfo);
                caseInfo.setAddress(baseCase.getHomeAddr());
                caseInfo.setCurrentCollector(user);
                caseInfo.setTransferDate(ZWDateUtil.getNowDateTime());
                caseInfo.setCaseDataStatus(CaseDataStatus.IN_POOL);
                caseInfo.setCaseType(request.getCaseType());
                caseInfo.setDepartment(null);
                caseInfo.setPublicCaseFlag(PublicCaseFlag.NO_PUBLIC_CASE);
                caseInfo.setLastContactResult(null);
                caseInfo.setLastContactDate(null);
                caseInfo.setOperator(userModel.getRealName());
                caseInfo.setOperatorTime(ZWDateUtil.getNowDateTime());
                caseTransferLogList.add(baseService.createCaseTranferLog(baseCase.getId(), "手动分案:分案到【".concat(user.getRealName()).concat("】"), userModel, null, user.getId(),caseInfo.getLeftAmt()));
                caseInfoList.add(caseInfo);
                baseCase.setIsDistribute(BaseSelect.YES);
                updateBaseCase.add(baseCase);
            }
        }
        caseInfoRepository.saveAll(caseInfoList);
        baseCaseRespository.saveAll(updateBaseCase);
        caseTransferLogRepository.saveAll(caseTransferLogList);

    }

    /**
     * @Author wangxiangdong
     * @Description 待分配催收员手动分案确认
     * @Date 2019/9/4 9:43
     **/
    @Transactional
    public void collectorConfirmCases(List<DistributeResultModel> distributeResultModelList, UserModel userModel) {
        List<CaseInfo> caseInfoList = new ArrayList<>();
        List<CaseTransferLog> caseTransferLogList = new ArrayList<>();
        for (DistributeResultModel distributeResultModel : distributeResultModelList) {
            String userId = distributeResultModel.getId();
            User user = userRepository.getOne(userId);
            Map<String, Double> resultMap = distributeResultModel.getResultMap();
            List<String> caseIds = new ArrayList<>();
            for (Map.Entry<String, Double> entry : resultMap.entrySet()) {
                caseIds.add(entry.getKey());
            }
            BooleanBuilder booleanBuilder = new BooleanBuilder();
            booleanBuilder.and(QCaseInfo.caseInfo.id.in(caseIds));
            Iterator<CaseInfo> iterator = caseInfoRepository.findAll(booleanBuilder).iterator();
            while (iterator.hasNext()) {
                CaseInfo caseInfo = iterator.next();
                String outUserId = (Objects.isNull(caseInfo.getCurrentCollector()) ? null : caseInfo.getCurrentCollector().getId());
                caseInfo.setCurrentCollector(user);
                caseInfo.setTransferDate(ZWDateUtil.getNowDateTime());
                caseInfo.setDepartment(null);
                caseInfo.setCaseDataStatus(CaseDataStatus.IN_POOL);
                caseInfo.setLastContactResult(null);
                caseInfo.setLastContactDate(null);
                caseInfo.setUpdateDate(ZWDateUtil.getNowDateTime());
                caseInfo.setUpdatePersonName(userModel.getRealName());
                if (!StringUtils.equals(outUserId, user.getId())) {
                    caseTransferLogList.add(baseService.createCaseTranferLog(caseInfo.getId(), "手动分案:分案到【".concat(user.getRealName()).concat("】"), userModel, outUserId, user.getId(),caseInfo.getLeftAmt()));
                }
                caseInfoList.add(caseInfo);
            }
        }
        caseInfoRepository.saveAll(caseInfoList);
        if(!caseTransferLogList.isEmpty()){
            caseTransferLogRepository.saveAll(caseTransferLogList);
        }
    }

    /**
     * @Author wangxiangdong
     * @Description 待分配批次数量 金额 统计
     * @Date 2019/9/12 11:16
     **/
    public CaseCountAndTotalResponse queryCountAndTotalByBatchNumber(String batchNumber) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termsQuery("batchNumber.keyword", batchNumber));
        boolQueryBuilder.must(QueryBuilders.termsQuery("isDistribute.keyword", BaseSelect.NO.name()));
        ValueCountAggregationBuilder valueCountAggregationBuilder = AggregationBuilders.count("caseCount").field("id.keyword");
        SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("leftAmtTotal").field("leftAmt");
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(Constants.BASE_CASE)
                .withTypes(Constants.BASE_CASE).withQuery(boolQueryBuilder).addAggregation(valueCountAggregationBuilder)
                .addAggregation(sumAggregationBuilder).build();
        Aggregations aggregations = elasticsearchTemplate.query(searchQuery, SearchResponse::getAggregations);
        Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
        CaseCountAndTotalResponse caseCountAndTotalResponse = new CaseCountAndTotalResponse();
        long caseCount = ((InternalValueCount) aggregationMap.get("caseCount")).getValue();
        double overdueAmountTotal = ((InternalSum) aggregationMap.get("leftAmtTotal")).getValue();
        caseCountAndTotalResponse.setCount(caseCount);
        caseCountAndTotalResponse.setOverdueAmountTotal(overdueAmountTotal);
        return caseCountAndTotalResponse;
    }

    /**
     * @Author wangxiangdong
     * @Description 获取批次分配可分配的批次号以及金额和数量
     * @Date 2019/9/10 16:32
     *
     * @param userModel*/
    public List<DistributeStatisticalResponse> getWaitBatchNumberAndTotal(UserModel userModel) {
        List<DistributeStatisticalResponse> distributeStatisticalResponses = new ArrayList<>();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(Objects.equals(userModel.getIsCheck(),BaseSelect.YES)){
            boolQueryBuilder.must(QueryBuilders.termsQuery("principalId.keyword", userModel.getPrincipalIds()));
        }
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("isDistribute.keyword", BaseSelect.NO.name()));
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("batchNumber").field("batchNumber.keyword");
        ValueCountAggregationBuilder valueCountAggregationBuilder = AggregationBuilders.count("caseCount").field("id.keyword");
        SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("leftAmtTotal").field("leftAmt");
        termsAggregationBuilder.subAggregation(valueCountAggregationBuilder);
        termsAggregationBuilder.subAggregation(sumAggregationBuilder);
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(Constants.BASE_CASE)
                .withTypes(Constants.BASE_CASE)
                .withQuery(boolQueryBuilder)
                .addAggregation(termsAggregationBuilder).build();
        Aggregations aggregations = elasticsearchTemplate.query(searchQuery, SearchResponse::getAggregations);
        Map<String, Aggregation> map = aggregations.asMap();
        if (map.get("batchNumber") instanceof StringTerms) {
            StringTerms stringTerms = (StringTerms) map.get("batchNumber");
            List<String> batchNumberList = new ArrayList<>();
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                DistributeStatisticalResponse distributeStatisticalResponse = new DistributeStatisticalResponse();
                batchNumberList.add(bucket.getKeyAsString());
                distributeStatisticalResponse.setBatchNumber(bucket.getKeyAsString());
                Map<String, Aggregation> subaggregationMap = bucket.getAggregations().getAsMap();
                long caseCount = ((InternalValueCount) subaggregationMap.get("caseCount")).getValue();
                double leftAmtTotal = ((InternalSum) subaggregationMap.get("leftAmtTotal")).getValue();
                distributeStatisticalResponse.setTotalAmount(leftAmtTotal);
                distributeStatisticalResponse.setTotalCount(BigInteger.valueOf(caseCount));
                distributeStatisticalResponses.add(distributeStatisticalResponse);
            }
        }
        return distributeStatisticalResponses;
    }


    /**
     * @param distributePoolType
     * @param userModel
     * @Author wangxiangdong
     * @Description 获取批次号以及金额统计
     * @Date 2019/9/12 14:09
     */
    public List<DistributeStatisticalResponse> getBatchNumberAndTotal(String distributePoolType, UserModel userModel) {
        List<DistributeStatisticalResponse> orgDistributeStatisticalList = new ArrayList<>();
        List<Object[]> orgBatchNumberAndTotal = new ArrayList<>();
        if (Objects.equals(distributePoolType, DistributePoolType.ORG_POOL.name())) {
            if(Objects.equals(userModel.getIsCheck(),BaseSelect.YES)){
                orgBatchNumberAndTotal = caseInfoRepository.getOrgBatchNumberAndTotal(userModel.getPrincipalIds());
            }else{
                orgBatchNumberAndTotal = caseInfoRepository.getOrgBatchNumberAndTotal();
            }
        }
        if (Objects.equals(distributePoolType, DistributePoolType.IN_POOL.name()) || Objects.equals(distributePoolType, DistributePoolType.CIRCULATION.name())) {
            if(Objects.equals(userModel.getIsCheck(),BaseSelect.YES)) {
                orgBatchNumberAndTotal = caseInfoRepository.getInCollectingBatchNumberAndTotal(distributePoolType,userModel.getPrincipalIds());
            }else{
                orgBatchNumberAndTotal = caseInfoRepository.getInCollectingBatchNumberAndTotal(distributePoolType);
            }
        }
        orgBatchNumberAndTotal.forEach(objectArr -> {
            DistributeStatisticalResponse orgStatisticalResponse = new DistributeStatisticalResponse();
            orgStatisticalResponse.setBatchNumber((String) objectArr[0]);
            orgStatisticalResponse.setTelNumber((BigInteger) objectArr[1]);
            orgStatisticalResponse.setTotalAmount((double)objectArr[2] + (double)objectArr[4]);
            orgStatisticalResponse.setVisitNumber((BigInteger) objectArr[3]);
            orgStatisticalResponse.setTotalCount(((BigInteger)objectArr[1]).add((BigInteger) objectArr[3]));
            orgDistributeStatisticalList.add(orgStatisticalResponse);
        });
        return orgDistributeStatisticalList;
    }

    public List<String> getSettleBatchNumber(UserModel userModel) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(Objects.equals(userModel.getIsCheck(),BaseSelect.YES)){
            boolQueryBuilder.must(QueryBuilders.termsQuery("principalId.keyword", userModel.getPrincipalIds()));
        }
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("isClear.keyword", BaseSelect.YES.name()));
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("batchNumber").field("batchNumber.keyword");
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(Constants.BASE_CASE)
                .withTypes(Constants.BASE_CASE)
                .withQuery(boolQueryBuilder)
                .addAggregation(termsAggregationBuilder).build();
        Aggregations aggregations = elasticsearchTemplate.query(searchQuery, SearchResponse::getAggregations);
        List<String> batchNumberList = new ArrayList<>();
        Map<String, Aggregation> map = aggregations.asMap();
        if (map.get("batchNumber") instanceof StringTerms) {
            StringTerms stringTerms = (StringTerms) map.get("batchNumber");
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                batchNumberList.add(bucket.getKeyAsString());
            }
        }
        return batchNumberList;
    }
}
